package com.jyf.redis.common.interceptor;

import com.jyf.redis.common.annotation.AccessLimit;
import com.jyf.redis.common.utils.RedisUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 接口防刷检查的拦截器
 * @author Mr.贾
 * @time 2020/10/20 14:46
 */
@Component
public class AccessLimitInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        //1、若方法上存在注解，就用方法上面的；若方法上面不存在注解，就用类上面的;若类上面也不存在注解，则放行。
        Method method = handlerMethod.getMethod();
        Class<?> declaringClass = method.getDeclaringClass();
        AccessLimit accessLimit = null;
        if (method.isAnnotationPresent(AccessLimit.class)){
            accessLimit = method.getAnnotation(AccessLimit.class);
        }else if (declaringClass.isAnnotationPresent(AccessLimit.class)){
            accessLimit = declaringClass.getAnnotation(AccessLimit.class);
        }else {
            return true;
        }
        //2、根据key从redis中获取当前接口已经访问的次数，和注解上面的最大访问次数最对比,若>=最大访问次数，就返回提示信息
        //key为ip/api/user/getUserById 格式
        String key = request.getRemoteAddr()+request.getRequestURI();
        //服务器上用这个 String clientIp = HttpContextUtils.getClientIP();
        String s = RedisUtils.get(key);
        if (null == s){
           RedisUtils.setex(key,accessLimit.second(),"1");
        }else {
            Integer accessCount =Integer.valueOf(s);
            if (accessCount >= accessLimit.maxLimit()){
               request.getRequestDispatcher("/exception/info/frequentlyAccess").forward(request, response);
               return false;
            }
            RedisUtils.incr(key);
        }

        return true;
    }
}
